/*
 * CC3OpenGLES11VertexArrays.m
 *
 * cocos3d 0.6.1
 * Author: Bill Hollings
 * Copyright (c) 2010-2011 The Brenwill Workshop Ltd. All rights reserved.
 * http://www.brenwill.com
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * http://en.wikipedia.org/wiki/MIT_License
 * 
 * See header file CC3OpenGLES11VertexArrays.h for full API documentation.
 */

#include "CC3OpenGLES11VertexArrays.h"


#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerArrayBufferBinding

//@implementation CC3OpenGLES11StateTrackerArrayBufferBinding
//
//@synthesize queryName;
//
//+(CC3GLESStateOriginalValueHandling) defaultOriginalValueHandling {
//	return kCC3GLESStateOriginalValueReadOnceAndRestore;
//}
//
//-(id) init {
//	if ( (self = [self initForState: GL_ARRAY_BUFFER]) ) {
//		self.queryName = GL_ARRAY_BUFFER_BINDING;
//	}
//	return self;
//}
//
//-(void) setGLValue {
//	glBindBuffer(name, value);
//}
//
//-(void) getGLValue {
//	glGetIntegerv(queryName, &originalValue);
//}
//
//-(void) logGetGLValue {
//	LogTrace("%@ %@ read GL value %i (was tracking %@)",
//			 [self class], NSStringFromGLEnum(queryName), originalValue,
//			 (valueIsKnown ? [NSString stringWithFormat: @"%i", value] : @"UNKNOWN"));
//}
//
//-(void) unbind {
//	self.value = 0;
//}
//
//-(void) loadBufferData: (GLvoid*) buffPtr  ofLength: (GLsizeiptr) buffLen forUse: (GLenum) buffUsage {
//	glBufferData(name, buffLen, buffPtr, buffUsage);
//}
//
//-(void) updateBufferData: (GLvoid*) buffPtr
//			  startingAt: (GLintptr) offset
//			   forLength: (GLsizeiptr) length {
//	glBufferSubData(name, offset, length, buffPtr);
//}
//
//@end

CC3OpenGLES11StateTrackerArrayBufferBinding::CC3OpenGLES11StateTrackerArrayBufferBinding()
{
	init();
}

CC3OpenGLES11StateTrackerArrayBufferBinding::~CC3OpenGLES11StateTrackerArrayBufferBinding()
{
}

void CC3OpenGLES11StateTrackerArrayBufferBinding::init()
{
	initForState(GL_ARRAY_BUFFER, NULL);
	setQueryName(GL_ARRAY_BUFFER_BINDING);
}

CC3OpenGLES11StateTrackerArrayBufferBinding* CC3OpenGLES11StateTrackerArrayBufferBinding::tracker()
{
	CC3OpenGLES11StateTrackerArrayBufferBinding* pState = new CC3OpenGLES11StateTrackerArrayBufferBinding;
	if (pState) 
	{
		pState->autorelease();
	}
	
	return pState;
}

void CC3OpenGLES11StateTrackerArrayBufferBinding::unbind()
{
	setValue(0);
}

void CC3OpenGLES11StateTrackerArrayBufferBinding::loadBufferData(GLvoid* buffPtr, GLsizeiptr buffLen, GLenum buffUsage)
{
	glBufferData(name, buffLen, buffPtr, buffUsage);
}

void CC3OpenGLES11StateTrackerArrayBufferBinding::updateBufferData(GLvoid* buffPtr, GLintptr offset, GLsizeiptr length)
{
	glBufferSubData(name, offset, length, buffPtr);
}

CC3GLESStateOriginalValueHandling CC3OpenGLES11StateTrackerArrayBufferBinding::defaultOriginalValueHandling()
{
	return kCC3GLESStateOriginalValueReadOnceAndRestore;
}

void CC3OpenGLES11StateTrackerArrayBufferBinding::setGLValue()
{
	glBindBuffer(name, value);
}

void CC3OpenGLES11StateTrackerArrayBufferBinding::getGLValue()
{
	glGetIntegerv(queryName, &originalValue);
}

void CC3OpenGLES11StateTrackerArrayBufferBinding::logGetGLValue()
{
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerElementArrayBufferBinding

//@implementation CC3OpenGLES11StateTrackerElementArrayBufferBinding
//
//-(id) init {
//	if ( (self = [self initForState: GL_ELEMENT_ARRAY_BUFFER]) ) {
//		self.queryName = GL_ELEMENT_ARRAY_BUFFER_BINDING;
//	}
//	return self;
//}
//
//@end

CC3OpenGLES11StateTrackerElementArrayBufferBinding::CC3OpenGLES11StateTrackerElementArrayBufferBinding()
{
	init();
}

void CC3OpenGLES11StateTrackerElementArrayBufferBinding::init()
{
	initForState(GL_ELEMENT_ARRAY_BUFFER, NULL);
	setQueryName(GL_ELEMENT_ARRAY_BUFFER_BINDING);
}

CC3OpenGLES11StateTrackerElementArrayBufferBinding* CC3OpenGLES11StateTrackerElementArrayBufferBinding::tracker()
{
	CC3OpenGLES11StateTrackerElementArrayBufferBinding* pState = new CC3OpenGLES11StateTrackerElementArrayBufferBinding;
	if (pState) 
	{
		pState->autorelease();
	}
	
	return pState;
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerVertexPointer

//@implementation CC3OpenGLES11StateTrackerVertexPointer
//
//@synthesize elementSize, elementType, elementStride, elementPointer;
//
//-(void) dealloc {
//	[elementSize release];
//	[elementType release];
//	[elementStride release];
//	[elementPointer release];
//	[super dealloc];
//}
//
//+(BOOL) defaultShouldAlwaysSetGL {
//	return YES;
//}
//
//-(void) initializeTrackers {}
//
//-(void) setOriginalValueHandling: (CC3GLESStateOriginalValueHandling) origValueHandling {
//	[super setOriginalValueHandling: origValueHandling];
//	elementSize.originalValueHandling = origValueHandling;
//	elementType.originalValueHandling = origValueHandling;
//	elementStride.originalValueHandling = origValueHandling;
//	elementPointer.originalValueHandling = origValueHandling;
//} 
//
//-(BOOL) valueIsKnown {
//	return elementPointer.valueIsKnown
//			&& elementStride.valueIsKnown
//			&& elementSize.valueIsKnown
//			&& elementType.valueIsKnown;
//}
//
//-(void) setValueIsKnown:(BOOL) aBoolean {
//	elementSize.valueIsKnown = aBoolean;
//	elementType.valueIsKnown = aBoolean;
//	elementStride.valueIsKnown = aBoolean;
//	elementPointer.valueIsKnown = aBoolean;
//}
//
//-(void) open {
//	[elementSize open];
//	[elementType open];
//	[elementStride open];
//	[elementPointer open];
//}
//
//-(void) restoreOriginalValue {
//	[self useElementsAt: elementPointer.originalValue
//			   withSize: elementSize.originalValue
//			   withType: elementType.originalValue
//			 withStride: elementStride.originalValue];
//}
//
//// Set the values in the GL engine if either we should always do it, or if something has changed
//-(void) useElementsAt: (GLvoid*) pData
//			 withSize: (GLint) elemSize
//			 withType: (GLenum) elemType
//		   withStride: (GLsizei) elemStride {
//	BOOL shouldSetGL = self.shouldAlwaysSetGL;
//	shouldSetGL |= [elementPointer attemptSetValue: pData];
//	shouldSetGL |= [elementSize attemptSetValue: elemSize];
//	shouldSetGL |= [elementType attemptSetValue: elemType];
//	shouldSetGL |= [elementStride attemptSetValue: elemStride];
//	if (shouldSetGL) {
//		[self setGLValues];
//	}
//	[self logSetGLValues: shouldSetGL];
//}
//
//-(void) useElementsAt: (GLvoid*) pData withType: (GLenum) elemType withStride: (GLsizei) elemStride {
//	[self useElementsAt: pData withSize: 0 withType: elemType withStride: elemStride];
//}
//
//-(void) setGLValues {}
//
//-(void) logSetGLValues: (BOOL) wasChanged {
//	if (elementSize.value != 0) {
//		// GL function uses element size
//		LogTrace("%@ %@ %@ = %i, %@ = %@, %@ = %i and %@ = %p", [self class], (wasChanged ? @"applied" : @"reused"),
//				 NSStringFromGLEnum(elementSize.name), elementSize.value,
//				 NSStringFromGLEnum(elementType.name), NSStringFromGLEnum(elementType.value),
//				 NSStringFromGLEnum(elementStride.name), elementStride.value,
//				 @"POINTER", elementPointer.value);
//	} else {
//		// GL function doesn't use element size
//		LogTrace("%@ %@ %@ = %@, %@ = %i and %@ = %p", [self class], (wasChanged ? @"applied" : @"reused"),
//				 NSStringFromGLEnum(elementType.name), NSStringFromGLEnum(elementType.value),
//				 NSStringFromGLEnum(elementStride.name), elementStride.value,
//				 @"POINTER", elementPointer.value);
//	}
//}
//
//-(NSString*) description {
//	NSMutableString* desc = [NSMutableString stringWithCapacity: 400];
//	[desc appendFormat: @"%@:", [self class]];
//	[desc appendFormat: @"\n    %@ ", elementSize];
//	[desc appendFormat: @"\n    %@ ", elementType];
//	[desc appendFormat: @"\n    %@ ", elementStride];
//	[desc appendFormat: @"\n    %@ ", elementPointer];
//	return desc;
//}
//
//@end

CC3OpenGLES11StateTrackerVertexPointer::CC3OpenGLES11StateTrackerVertexPointer() :
	elementSize(NULL),
	elementType(NULL),
	elementStride(NULL),
	elementPointer(NULL)
{
}

CC3OpenGLES11StateTrackerVertexPointer::~CC3OpenGLES11StateTrackerVertexPointer()
{
	elementSize->release();
	elementType->release();
	elementStride->release();
	elementPointer->release();
}

bool CC3OpenGLES11StateTrackerVertexPointer::defaultShouldAlwaysSetGL()
{
	return true;
}

void CC3OpenGLES11StateTrackerVertexPointer::initializeTrackers()
{
}

bool CC3OpenGLES11StateTrackerVertexPointer::getValueIsKnown()
{
	return elementPointer->getValueIsKnown()
	&& elementStride->getValueIsKnown()
	&& elementSize->getValueIsKnown()
	&& elementType->getValueIsKnown();
}

void CC3OpenGLES11StateTrackerVertexPointer::setValueIsKnown(bool aBoolean)
{
	elementSize->setValueIsKnown(aBoolean);
	elementType->setValueIsKnown(aBoolean);
	elementStride->setValueIsKnown(aBoolean);
	elementPointer->setValueIsKnown(aBoolean);
}

void CC3OpenGLES11StateTrackerVertexPointer::open()
{
	elementSize->open();
	elementType->open();
	elementStride->open();
	elementPointer->open();
}

void CC3OpenGLES11StateTrackerVertexPointer::restoreOriginalValue()
{
	useElementsAt(elementPointer->getOriginalValue(),
				  elementSize->getOriginalValue(),
				  elementType->getOriginalValue(),
				  elementStride->getOriginalValue());
}

void CC3OpenGLES11StateTrackerVertexPointer::useElementsAt(GLvoid* pData, GLint elemSize, GLenum elemType, GLsizei elemStride)
{
	bool shouldSetGL = getShouldAlwaysSetGL();
	shouldSetGL |= elementPointer->attemptSetValue(pData);
	shouldSetGL |= elementSize->attemptSetValue(elemSize);
	shouldSetGL |= elementType->attemptSetValue(elemType);
	shouldSetGL |= elementStride->attemptSetValue(elemStride);
	if (shouldSetGL) 
	{
		setGLValues();
	}
	
	logSetGLValues(shouldSetGL);
}

void CC3OpenGLES11StateTrackerVertexPointer::useElementsAt(GLvoid* pData, GLenum elemType, GLsizei elemStride)
{
	useElementsAt(pData, 0, elemType, elemStride);
}

void CC3OpenGLES11StateTrackerVertexPointer::setGLValues()
{
}

void CC3OpenGLES11StateTrackerVertexPointer::logSetGLValues(bool wasChanged)
{
	if (elementSize->getValue() != 0) 
	{
		// GL function uses element size
		//LogTrace("%@ %@ %@ = %i, %@ = %@, %@ = %i and %@ = %p", [self class], (wasChanged ? @"applied" : @"reused"),
//				 NSStringFromGLEnum(elementSize.name), elementSize.value,
//				 NSStringFromGLEnum(elementType.name), NSStringFromGLEnum(elementType.value),
//				 NSStringFromGLEnum(elementStride.name), elementStride.value,
//				 @"POINTER", elementPointer.value);
	} 
	else 
	{
		// GL function doesn't use element size
		//LogTrace("%@ %@ %@ = %@, %@ = %i and %@ = %p", [self class], (wasChanged ? @"applied" : @"reused"),
//				 NSStringFromGLEnum(elementType.name), NSStringFromGLEnum(elementType.value),
//				 NSStringFromGLEnum(elementStride.name), elementStride.value,
//				 @"POINTER", elementPointer.value);
	}
}

void CC3OpenGLES11StateTrackerVertexPointer::setOriginalValueHandling(CC3GLESStateOriginalValueHandling origValueHandling)
{
	CC3OpenGLES11StateTrackerComposite::setOriginalValueHandling(origValueHandling);
	elementSize->setOriginalValueHandling(origValueHandling);
	elementType->setOriginalValueHandling(origValueHandling);
	elementStride->setOriginalValueHandling(origValueHandling);
	elementPointer->setOriginalValueHandling(origValueHandling);
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerVertexLocationsPointer

//@implementation CC3OpenGLES11StateTrackerVertexLocationsPointer
//
//-(void) initializeTrackers {
//	self.elementSize = [CC3OpenGLES11StateTrackerInteger trackerForState: GL_VERTEX_ARRAY_SIZE];
//	self.elementType = [CC3OpenGLES11StateTrackerEnumeration trackerForState: GL_VERTEX_ARRAY_TYPE];
//	self.elementStride = [CC3OpenGLES11StateTrackerInteger trackerForState: GL_VERTEX_ARRAY_STRIDE];
//	self.elementPointer = [CC3OpenGLES11StateTrackerPointer tracker];
//}
//
//-(void) setGLValues {
//	glVertexPointer(elementSize.value, elementType.value, elementStride.value, elementPointer.value);
//}
//
//@end

void CC3OpenGLES11StateTrackerVertexLocationsPointer::initializeTrackers()
{
	setElementSize(CC3OpenGLES11StateTrackerInteger::trackerForState(GL_VERTEX_ARRAY_SIZE, NULL));
	setElementType(CC3OpenGLES11StateTrackerEnumeration::trackerForState(GL_VERTEX_ARRAY_TYPE));
	setElementStride(CC3OpenGLES11StateTrackerInteger::trackerForState(GL_VERTEX_ARRAY_STRIDE, NULL));
	setElementPointer(CC3OpenGLES11StateTrackerPointer::tracker());
}

void CC3OpenGLES11StateTrackerVertexLocationsPointer::setGLValues()
{
	glVertexPointer(elementSize->getValue(), elementType->getValue(), elementStride->getValue(), elementPointer->getValue());
}

CC3OpenGLES11StateTrackerVertexLocationsPointer* CC3OpenGLES11StateTrackerVertexLocationsPointer::tracker()
{
	CC3OpenGLES11StateTrackerVertexLocationsPointer* pState = new CC3OpenGLES11StateTrackerVertexLocationsPointer;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerVertexNormalsPointer

//@implementation CC3OpenGLES11StateTrackerVertexNormalsPointer
//
//-(void) initializeTrackers {
//	self.elementSize = [CC3OpenGLES11StateTrackerInteger tracker];		// no-op tracker
//	self.elementType = [CC3OpenGLES11StateTrackerEnumeration trackerForState: GL_NORMAL_ARRAY_TYPE];
//	self.elementStride = [CC3OpenGLES11StateTrackerInteger trackerForState: GL_NORMAL_ARRAY_STRIDE];
//	self.elementPointer = [CC3OpenGLES11StateTrackerPointer tracker];
//}
//
//-(void) setGLValues {
//	glNormalPointer(elementType.value, elementStride.value, elementPointer.value);
//}
//
//@end

void CC3OpenGLES11StateTrackerVertexNormalsPointer::initializeTrackers()
{
	setElementSize(CC3OpenGLES11StateTrackerInteger::tracker());		// no-op tracker
	setElementType(CC3OpenGLES11StateTrackerEnumeration::trackerForState(GL_NORMAL_ARRAY_TYPE));
	setElementStride(CC3OpenGLES11StateTrackerInteger::trackerForState(GL_NORMAL_ARRAY_STRIDE, NULL));
	setElementPointer(CC3OpenGLES11StateTrackerPointer::tracker());
}

void CC3OpenGLES11StateTrackerVertexNormalsPointer::setGLValues()
{
	glNormalPointer(elementType->getValue(), elementStride->getValue(), elementPointer->getValue());
}

CC3OpenGLES11StateTrackerVertexNormalsPointer* CC3OpenGLES11StateTrackerVertexNormalsPointer::tracker()
{
	CC3OpenGLES11StateTrackerVertexNormalsPointer* pState = new CC3OpenGLES11StateTrackerVertexNormalsPointer;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerVertexColorsPointer
//
//@implementation CC3OpenGLES11StateTrackerVertexColorsPointer
//
//-(void) initializeTrackers {
//	self.elementSize = [CC3OpenGLES11StateTrackerInteger trackerForState: GL_COLOR_ARRAY_SIZE];
//	self.elementType = [CC3OpenGLES11StateTrackerEnumeration trackerForState: GL_COLOR_ARRAY_TYPE];
//	self.elementStride = [CC3OpenGLES11StateTrackerInteger trackerForState: GL_COLOR_ARRAY_STRIDE];
//	self.elementPointer = [CC3OpenGLES11StateTrackerPointer tracker];
//}
//
//-(void) setGLValues {
//	glColorPointer(elementSize.value, elementType.value, elementStride.value, elementPointer.value);
//}
//
//@end

void CC3OpenGLES11StateTrackerVertexColorsPointer::initializeTrackers()
{
	setElementSize(CC3OpenGLES11StateTrackerInteger::trackerForState(GL_COLOR_ARRAY_SIZE, NULL));
	setElementType(CC3OpenGLES11StateTrackerEnumeration::trackerForState(GL_COLOR_ARRAY_TYPE));
	setElementStride(CC3OpenGLES11StateTrackerInteger::trackerForState(GL_COLOR_ARRAY_STRIDE, NULL));
	setElementPointer(CC3OpenGLES11StateTrackerPointer::tracker());
}

void CC3OpenGLES11StateTrackerVertexColorsPointer::setGLValues()
{
	glColorPointer(elementSize->getValue(), elementType->getValue(), elementStride->getValue(), elementPointer->getValue());
}

CC3OpenGLES11StateTrackerVertexColorsPointer* CC3OpenGLES11StateTrackerVertexColorsPointer::tracker()
{
	CC3OpenGLES11StateTrackerVertexColorsPointer* pState = new CC3OpenGLES11StateTrackerVertexColorsPointer;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

#pragma mark -
#pragma mark CC3OpenGLES11StateTrackerVertexPointSizesPointer

//@implementation CC3OpenGLES11StateTrackerVertexPointSizesPointer
//
//-(void) initializeTrackers {
//	self.elementSize = [CC3OpenGLES11StateTrackerInteger tracker];		// no-op tracker
//	self.elementType = [CC3OpenGLES11StateTrackerEnumeration trackerForState: GL_POINT_SIZE_ARRAY_TYPE_OES];
//	self.elementStride = [CC3OpenGLES11StateTrackerInteger trackerForState: GL_POINT_SIZE_ARRAY_STRIDE_OES];
//	self.elementPointer = [CC3OpenGLES11StateTrackerPointer tracker];
//}
//
//-(void) setGLValues {
//	glPointSizePointerOES(elementType.value, elementStride.value, elementPointer.value);
//}
//
//@end

void CC3OpenGLES11StateTrackerVertexPointSizesPointer::initializeTrackers()
{
	setElementSize(CC3OpenGLES11StateTrackerInteger::tracker());
	setElementType(CC3OpenGLES11StateTrackerEnumeration::trackerForState(GL_POINT_SIZE_ARRAY_TYPE_OES));
	setElementStride(CC3OpenGLES11StateTrackerInteger::trackerForState(GL_POINT_SIZE_ARRAY_STRIDE_OES, NULL));
	setElementPointer(CC3OpenGLES11StateTrackerPointer::tracker());
}

void CC3OpenGLES11StateTrackerVertexPointSizesPointer::setGLValues()
{
	glPointSizePointerOES(elementType->getValue(), elementStride->getValue(), elementPointer->getValue());
}

CC3OpenGLES11StateTrackerVertexPointSizesPointer* CC3OpenGLES11StateTrackerVertexPointSizesPointer::tracker()
{
	CC3OpenGLES11StateTrackerVertexPointSizesPointer* pState = new CC3OpenGLES11StateTrackerVertexPointSizesPointer;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

#pragma mark -
#pragma mark CC3OpenGLES11VertexArrays

//@implementation CC3OpenGLES11VertexArrays
//
//@synthesize arrayBuffer;
//@synthesize indexBuffer;
//@synthesize locations;
//@synthesize normals;
//@synthesize colors;
//@synthesize pointSizes;
//
//-(void) dealloc {
//	[arrayBuffer release];
//	[indexBuffer release];
//	[locations release];
//	[normals release];
//	[colors release];
//	[pointSizes release];
//	[super dealloc];
//}
//
//-(void) initializeTrackers {
//	self.arrayBuffer = [CC3OpenGLES11StateTrackerArrayBufferBinding tracker];
//	self.indexBuffer = [CC3OpenGLES11StateTrackerElementArrayBufferBinding tracker];
//	self.locations = [CC3OpenGLES11StateTrackerVertexLocationsPointer tracker];
//	self.normals = [CC3OpenGLES11StateTrackerVertexNormalsPointer tracker];
//	self.colors = [CC3OpenGLES11StateTrackerVertexColorsPointer tracker];
//	self.pointSizes = [CC3OpenGLES11StateTrackerVertexPointSizesPointer tracker];
//}
//
//-(CC3OpenGLES11StateTrackerArrayBufferBinding*) bufferBinding: (GLenum) bufferTarget {
//	switch (bufferTarget) {
//		case GL_ARRAY_BUFFER:
//			return arrayBuffer;
//		case GL_ELEMENT_ARRAY_BUFFER:
//			return indexBuffer;
//		default:
//			NSAssert1(NO, @"Illegal buffer target %u", bufferTarget);
//			return nil;
//	}
//}
//
//-(void) open {
//	LogTrace("Opening %@", [self class]);
//	[arrayBuffer open];
//	[indexBuffer open];
//	[locations open];
//	[normals open];
//	[colors open];
//	[pointSizes open];
//}
//
//-(void) close {
//	LogTrace("Closing %@", [self class]);
//	[arrayBuffer close];
//	[indexBuffer close];
//	[locations close];
//	[normals close];
//	[colors close];
//	[pointSizes close];
//}
//
//-(GLuint) generateBuffer {
//	GLuint buffID;
//	glGenBuffers(1, &buffID);
//	return buffID;
//}
//
//-(void) deleteBuffer: (GLuint) buffID  {
//	glDeleteBuffers(1, &buffID);
//}
//
//-(void) drawVerticiesAs: (GLenum) drawMode startingAt: (GLuint) start withLength: (GLuint) len {
//	glDrawArrays(drawMode, start, len);
//} 
//
//-(void) drawIndicies: (GLvoid*) indicies ofLength: (GLuint) len andType: (GLenum) type as: (GLenum) drawMode {
//	glDrawElements(drawMode, len, type, indicies);
//} 
//
//-(NSString*) description {
//	NSMutableString* desc = [NSMutableString stringWithCapacity: 600];
//	[desc appendFormat: @"%@:", [self class]];
//	[desc appendFormat: @"\n    %@ ", arrayBuffer];
//	[desc appendFormat: @"\n    %@ ", indexBuffer];
//	[desc appendFormat: @"\n    %@ ", locations];
//	[desc appendFormat: @"\n    %@ ", normals];
//	[desc appendFormat: @"\n    %@ ", colors];
//	[desc appendFormat: @"\n    %@ ", pointSizes];
//	return desc;
//}
//
//@end

CC3OpenGLES11VertexArrays::CC3OpenGLES11VertexArrays() :
	arrayBuffer(NULL),
	indexBuffer(NULL),
	locations(NULL),
	normals(NULL),
	colors(NULL),
	pointSizes(NULL)
{
	
}

CC3OpenGLES11VertexArrays::~CC3OpenGLES11VertexArrays()
{
	arrayBuffer->release();
	indexBuffer->release();
	locations->release();
	normals->release();
	colors->release();
	pointSizes->release();
}

CC3OpenGLES11VertexArrays* CC3OpenGLES11VertexArrays::tracker()
{
	CC3OpenGLES11VertexArrays* pState = new CC3OpenGLES11VertexArrays;
	if (pState) 
	{
		pState->initializeTrackers();
		pState->autorelease();
	}
	
	return pState;
}

void CC3OpenGLES11VertexArrays::initializeTrackers()
{
	setArrayBuffer(CC3OpenGLES11StateTrackerArrayBufferBinding::tracker());
	setIndexBuffer(CC3OpenGLES11StateTrackerElementArrayBufferBinding::tracker());
	setLocations(CC3OpenGLES11StateTrackerVertexLocationsPointer::tracker());
	setNormals(CC3OpenGLES11StateTrackerVertexNormalsPointer::tracker());
	setColors(CC3OpenGLES11StateTrackerVertexColorsPointer::tracker());
	setPointSizes(CC3OpenGLES11StateTrackerVertexPointSizesPointer::tracker());
}

CC3OpenGLES11StateTrackerArrayBufferBinding* CC3OpenGLES11VertexArrays::bufferBinding(GLenum bufferTarget)
{
	switch (bufferTarget) 
	{
		case GL_ARRAY_BUFFER:
			return arrayBuffer;
		case GL_ELEMENT_ARRAY_BUFFER:
			return indexBuffer;
		default:
			//NSAssert1(NO, @"Illegal buffer target %u", bufferTarget);
			return NULL;
	}
}

void CC3OpenGLES11VertexArrays::open()
{
	arrayBuffer->open();
	indexBuffer->open();
	locations->open();
	normals->open();
	colors->open();
	pointSizes->open();
}

void CC3OpenGLES11VertexArrays::close()
{
	//LogTrace("Closing %@", [self class]);
	arrayBuffer->close();
	indexBuffer->close();
	locations->close();
	normals->close();
	colors->close();
	pointSizes->close();
}

GLuint CC3OpenGLES11VertexArrays::generateBuffer()
{
	GLuint buffID;
	glGenBuffers(1, &buffID);
	return buffID;
}

void CC3OpenGLES11VertexArrays::deleteBuffer(GLuint buffID)
{
	glDeleteBuffers(1, &buffID);
}

void CC3OpenGLES11VertexArrays::drawVerticiesAs(GLenum drawMode, GLuint start, GLuint len)
{
	glDrawArrays(drawMode, start, len);
}

void CC3OpenGLES11VertexArrays::drawIndicies(GLvoid* indicies, GLuint len, GLenum type, GLenum drawMode)
{
	glDrawElements(drawMode, len, type, indicies);
}



